package interactive.turntable
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.utils.getTimer;
	
	/**
	 * 转盘
	 * 功能:   设置初始角度 
		       控制转速
	 *         控制结果角度
	 * 
	 * 转动完成后发出Event.COMPLETE事件
	 * @author Ning
	 */
	public class Turntable extends Sprite 
	{
		//转速
		private var _speed:Number;
		//加速度
		private var _acceleration:Number;
		//减速度
		private var _decelerate:Number;
		//默认角度
		private var _defaultAngle:Number;
		//结果角度
		private var _resultAngle:Number=90;
		//匀速转动时间  由于通过此时间进行结果判定，所以实际转动时间不会精确
		private var _time:Number;
		//误差
		private var _inaccuracy:Number = 0.15;

		
		//当前转速
		private var _v:Number = 0;
		//当前加速度
		private var _a:Number = 0;
		//状态0 加速 1匀速 2第一次减速  3寻找真正减速点 4减速
		private var _status:int = 0;
		//匀速开始时间
		private var _uniformStartTime:Number = 0;
		//开如减速的角度
		private var _decelerateAngle:Number = 0;
		
	
		
		
		public function Turntable(speed:Number=5,defaultAngle:Number=0,time:Number=5000,acceleration:Number=.1,decelerate:Number=.1,inaccuracy:Number=1.5) 
		{
			this.speed = speed;
			this.defaultAngle = defaultAngle;
			this.time = time;
			this.acceleration = acceleration;
			this.decelerate = decelerate;
			this.inaccuracy = inaccuracy;
			addEventListener(Event.REMOVED_FROM_STAGE, onRemoveFromStage);
			refresh();
		}
		/**
		 * 刷新
		 */
		public function refresh():void
		{
			this.rotation = defaultAngle;
		}
		
		public function play():void
		{
			
			_a = acceleration;
			_status = 0;
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
		//从舞台离开
		private function onRemoveFromStage(evt:Event):void
		{
			removeEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
		
		private function onEnterFrame(evt:Event):void
		{
			
			//加速状态
			if (_status == 0)
			{
				if (_v >= speed)
				{
					_v = speed;
					_a = 0;
				    _uniformStartTime = getTimer();
					_status = 1;
				}   
			}
			//匀速状态
			else if (_status == 1)
			{
				var now:Number = getTimer();
				if ((now - _uniformStartTime) >= time)
				{
					_a = -1 * decelerate;
					_status = 2;
				}
			}
			//第一次减速 速度减到2.9-3.1时变为匀速
			else if (_status == 2)
	        {
				if (_v > 2.9 && _v < 3.1)
				{
					_a = 0;
					_decelerateAngle = getDecelerateAngle(_v);
					_status = 3;
				}
			}
			//寻找减速点
			else if (_status == 3)
			{
				//inaccuracy为误差值
				if (getAngleRemainder(this.rotation, _decelerateAngle) < inaccuracy)
				{
					_a = -1 * decelerate;
					_status = 4;
				}
			}
			else if (_status == 4)
			{
				if (_v <= 0)
				{
					_v = 0;
					removeEventListener(Event.ENTER_FRAME, onEnterFrame);
					dispatchEvent(new Event(Event.COMPLETE));
					return;
				}
			}
			_v += _a;
			this.rotation += _v; 
		}
		
		
		public function get speed():Number 
		{
			return _speed;
		}
		
		public function set speed(value:Number):void 
		{
			_speed = value;
		}
		
		public function get acceleration():Number 
		{
			return _acceleration;
		}
		
		public function set acceleration(value:Number):void 
		{
			_acceleration = value;
		}
		
		public function get defaultAngle():Number 
		{
			return _defaultAngle;
		}
		
		public function set defaultAngle(value:Number):void 
		{
			_defaultAngle = value;
		}
		
		public function get resultAngle():Number 
		{
			return _resultAngle;
		}
		
		public function set resultAngle(value:Number):void 
		{
			_resultAngle = value;
		}
		
		public function get time():Number 
		{
			return _time;
		}
		
		public function set time(value:Number):void 
		{
			_time = value;
		}
		
		public function get decelerate():Number 
		{
			return _decelerate;
		}
		
		public function set decelerate(value:Number):void 
		{
			_decelerate = value;
		}
		
		public function get inaccuracy():Number 
		{
			return _inaccuracy;
		}
		
		public function set inaccuracy(value:Number):void 
		{
			_inaccuracy = value;
		}

		
		//返回指定速度时的减速角度值
		private function getDecelerateAngle(speed:Number):Number
		{
			//返回减速后移动的角度值
			var rotation:Number = 0;
			calculate(speed);
			function calculate(v:Number):void
			{
				v -= decelerate;
				if (v > 0) {
					rotation += v;
					calculate(v);
				}
			}
			return get360Angle((get360Angle(resultAngle) - rotation));
		}
		//返回a距离b多少角度
		public function getAngleRemainder(rotationA:Number, rotationB:Number):Number
		{
			var r:Number = get360Angle(rotationA)-get360Angle(rotationB);
			return Math.abs(r);
		}
		//返回360度的角度
		private function get360Angle(angle:Number):Number
		{
			if (angle < 0)
				    return angle + 360;
				else 
				    return angle;
		}
	}
}